package lnx

/*
#cgo CPPFLAGS: -fPIC -I../include
#cgo linux LDFLAGS: -fPIC -L${SRCDIR} -Wl,-rpath ${SRCDIR} -lhs_quote -lstdc++

#include "HSDataType.h"
#include "HSStruct.h"
void* qCreateApi();
void* qCreateSpi();
void* qGetVersion();
//  删除接口对象本身
void* qReleaseApi(void* api);
//              pszSafeLevel          安全级别
void* qInit(void* api, const char *pszLicFile, const char *pszSafeLevel, const char *pszPwd, const char *pszSslFile, const char *pszSslPwd);
//  API和交易柜台建立连接，连接建立成功后，主线程会等待用户操作子线程退出
void* qJoin(void* api);
//  注册前置机网络地址
void* qRegisterFront(void* api, const char *pszFrontAddress);
//  注册Fens网络地址
void* qRegisterFensServer(void* api, const char *pszFensAddress, const char *pszAccountID);
//  注册回调接口
void* qRegisterSpi(void* api, void *pSpi);
//  订阅-行情请求
void* qReqDepthMarketDataSubscribe(void* api, struct CHSReqDepthMarketDataField pReqDepthMarketDataSubscribe[], int nCount, int nRequestID);
//  订阅取消-行情请求
void* qReqDepthMarketDataCancel(void* api, struct CHSReqDepthMarketDataField pReqDepthMarketDataCancel[], int nCount, int nRequestID);

//  当客户端与交易后台开始建立通信连接，连接成功后此方法被回调。
void qSetOnFrontConnected(void*, void*);
void qFrontConnected(void* spi);
// 当客户端与交易后台通信连接异常时，该方法被调用。
void qSetOnFrontDisconnected(void*, void*);
void qFrontDisconnected(void* spi, int nResult);
//  订阅-行情应答
void qSetOnRspDepthMarketDataSubscribe(void*, void*);
void qRspDepthMarketDataSubscribe(void* spi, struct CHSRspInfoField *pRspInfo, int nRequestID, _Bool bIsLast);
//  订阅取消-行情应答
void qSetOnRspDepthMarketDataCancel(void*, void*);
void qRspDepthMarketDataCancel(void* spi, struct CHSRspInfoField *pRspInfo, int nRequestID, _Bool bIsLast);
//  主推-行情
void qSetOnRtnDepthMarketData(void*, void*);
void qRtnDepthMarketData(void* spi, struct CHSDepthMarketDataField *pDepthMarketData);

#include <stdlib.h>
#include <stdint.h>
*/
import "C"

import (
	"unsafe"

	"gitee.com/haifengat/gohs/def"
)

var q *Quote

// Quote 行情接口
type Quote struct {
	api unsafe.Pointer

	//  当客户端与交易后台开始建立通信连接，连接成功后此方法被回调。
	OnFrontConnected func()
	// 当客户端与交易后台通信连接异常时，该方法被调用。
	OnFrontDisconnected func(nResult int)
	//  订阅-行情应答
	OnRspDepthMarketDataSubscribe func(pRspInfo *def.CHSRspInfoField, nRequestID int, bIsLast bool)
	//  订阅取消-行情应答
	OnRspDepthMarketDataCancel func(pRspInfo *def.CHSRspInfoField, nRequestID int, bIsLast bool)
	//  主推-行情
	OnRtnDepthMarketData func(pDepthMarketData *def.CHSDepthMarketDataField)
}

/*
注册前置地址

	连接UFT系统时地址前缀为tcp://
	连接UST系统时地址前缀为ust://
	行情API 初始化
	连接UFT系统时传入许可证路径
	连接UST系统时无需许可证
*/
func (q *Quote) ReqConnect(addr, licFile string) {
	addrCopy := make([]byte, len(addr))
	copy(addrCopy, addr) // 传递副本
	front := C.CString(string(addrCopy))
	C.qRegisterFront(q.api, front)
	defer C.free(unsafe.Pointer(front))
	/// Description: 初始化连接
	///              pszLicFile            通讯证书
	///              pszSafeLevel          安全级别
	///              pszPwd                通讯密码
	///              pszSslFile            SSL证书
	///              pszSslPwd             SSL密码
	// void* qInit(void* api, const char *pszLicFile, const char *pszSafeLevel, const char *pszPwd, const char *pszSslFile, const char *pszSslPwd);
	licCopy := make([]byte, len(licFile))
	copy(licCopy, []byte(licFile))
	lic := C.CString(string(licCopy))
	space := ""
	cSpace := C.CString(space)
	defer C.free(unsafe.Pointer(cSpace))
	C.qInit(q.api, lic, cSpace, cSpace, cSpace, cSpace)
	// C.qJoin(q.api)
}

func (q *Quote) ReleaseAPI() {
	C.qRegisterSpi(q.api, nil)
	C.qReleaseApi(q.api)
	q.api = nil
}

func (q *Quote) ReqSubMarketData(instrument string) {
	f := def.CHSReqDepthMarketDataField{}
	copy(f.InstrumentID[:], []byte(instrument))
	C.qReqDepthMarketDataSubscribe(q.api, (*C.struct_CHSReqDepthMarketDataField)(unsafe.Pointer(&f)), C.int(1), C.int(1))
}

// NewQuote 实例化
func NewQuote() *Quote {
	q = new(Quote)

	q.api = C.qCreateApi()
	spi := C.qCreateSpi()
	C.qRegisterSpi(q.api, spi)

	C.qSetOnFrontConnected(spi, C.qFrontConnected)
	C.qSetOnFrontDisconnected(spi, C.qFrontDisconnected)
	C.qSetOnRspDepthMarketDataSubscribe(spi, C.qRspDepthMarketDataSubscribe)
	C.qSetOnRspDepthMarketDataCancel(spi, C.qRspDepthMarketDataCancel)
	C.qSetOnRtnDepthMarketData(spi, C.qRtnDepthMarketData)

	return q
}

//export qFrontConnected
func qFrontConnected(spi unsafe.Pointer) {
	if q.OnFrontConnected != nil {
		q.OnFrontConnected()
	}
}

//export qFrontDisconnected
func qFrontDisconnected(spi unsafe.Pointer, nResult C.int) {
	if q.OnFrontDisconnected != nil {
		q.OnFrontDisconnected(int(nResult))
	}
}

//export qRspDepthMarketDataSubscribe
func qRspDepthMarketDataSubscribe(spi unsafe.Pointer, pRspInfo *C.struct_CHSRspInfoField, nRequestID C.int, bIsLast C._Bool) {
	if q.OnRspDepthMarketDataSubscribe != nil {
		q.OnRspDepthMarketDataSubscribe((*def.CHSRspInfoField)(unsafe.Pointer(pRspInfo)), int(nRequestID), bool(bIsLast))
	}
}

//export qRspDepthMarketDataCancel
func qRspDepthMarketDataCancel(spi unsafe.Pointer, pRspInfo *C.struct_CHSRspInfoField, nRequestID C.int, bIsLast C._Bool) {
	if q.OnRspDepthMarketDataCancel != nil {
		q.OnRspDepthMarketDataCancel((*def.CHSRspInfoField)(unsafe.Pointer(pRspInfo)), int(nRequestID), bool(bIsLast))
	}
}

//export qRtnDepthMarketData
func qRtnDepthMarketData(spi unsafe.Pointer, pDepthMarketData *C.struct_CHSDepthMarketDataField) {
	if q.OnRtnDepthMarketData != nil {
		q.OnRtnDepthMarketData((*def.CHSDepthMarketDataField)(unsafe.Pointer(pDepthMarketData)))
	}
}
